#ifndef _H_PACKDATA
#define _H_PACKDATA

#include "registers.h"

/*
 * ================== DeviceData
 */

// Need to think about cell id's.
//
// BUGBUG: numCells is funky. It should only be set after setting
// all voltages.
//
// cellId is the (device+cell) Id 
// cellNumber is simply the number for a device.
// Both cellId and cellNumber are 1-based
//
class PackData;
class DeviceData
{
  uint8_t deviceId;
  uint16_t cellOffsetId;        // starting cell id for this device
                                // cell id is offset from this.
  uint8_t numCells;
  uint16_t enabledCellsMask;    // mask of enabled cells

  PackData* pack;
  uint16_t cellVoltages[MAXDEVICECELLS];

public:
  // stats for the entire pack
  static uint8_t totCells;
  static uint16_t minVoltage;
  static uint16_t maxVoltage;
  static uint16_t avgVoltage;
  static uint32_t totVoltage;

private:
  inline void printHdr();
  inline void printTrailer();

public:
  DeviceData(uint8_t d, PackData* pd);
  void setCellVoltage(uint8_t cellNumber, uint16_t voltage);
  float getCellVoltage(uint8_t cellNumber);
  void setCellOffsetId(uint16_t offset);
  boolean disableNullCells(uint16_t& startingCellId,
                           uint16_t& cellMask);
  void printCellVoltages(boolean filterNulls = true);
  void printUVcellVoltages();

  // initializes stats before accumulating it.
  static void initStatCellVoltages();
  void setStatCellVoltages();
  static void printStatCellVoltages();
};


/*
 * ================== PackData
 */

// Pack Data, should be a singleton.
class PackData
{
  // Device-cell voltages
  DeviceData *deviceData[MAXDEVICES];
  
  uint8_t numDevices;
  uint16_t maxCells;

  // over & voltage thresholds also part of this class.

  static PackData* loneSingleton;

public:
  PackData();
  ~PackData();

  static PackData* singleton() {return loneSingleton;}

  void clear();
  void setNumDevices(uint8_t nd);
  uint8_t getNumDevices();
  void setCellData(RegCellData& cellData);

  // print number of cells. MUST be called ONLY after 
  // call to disableNullCells
  void printNumCells();

  // Print all cell voltages
  void printCellVoltages(boolean filterNoise=true);

  // print all data
  void print();

  // print interesting stats for cell voltages
  void printStatCellVoltages();

  // disable null cells from being scanned
  // Also, sets cell offsetIds, which reflect real cell Ids.
  boolean disableNullCells();

  // read cell voltages
  boolean readCellVoltages();

  // initiate scanning.
  boolean scan();

  // Return true if any device is under voltage.
  boolean isDeviceUV();

  // print UV cell voltages
  void printUVcellVoltages();
};

#endif
